#include "wnditem.h"
#include <QtCore>
#include <QtGui>
#include "QWndAction.h"


BOOL CALLBACK WndItems::EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
	WndItems * pItems = (WndItems *) lParam;

	// filter style
	DWORD dwStyle = ::GetWindowLongA(hwnd, GWL_STYLE);
	if (!(dwStyle & pItems->m_dwStyleFilter))
		return TRUE;

	if (pItems->m_map.contains(hwnd))
		return TRUE;

	// get title
	WCHAR wTitle[MAX_PATH];
	::GetWindowTextW(hwnd, wTitle, MAX_PATH);
	const QString sTitle = QString::fromUtf16((ushort*)wTitle);
	if (sTitle.isEmpty())
		return TRUE;

	// get class name
	WCHAR wClassName[MAX_PATH];
	::GetClassNameW(hwnd, wClassName, MAX_PATH);
	const QString sClassName = QString::fromUtf16((ushort*)wClassName);
	if (sClassName.isEmpty())
		return TRUE;

	WndItem * pNewItem = new WndItem(hwnd, sTitle, sClassName);

	pNewItem->loadHotKey(*pItems->m_pSettings);

	pItems->m_map[hwnd] = SPWndItem(pNewItem);

	return TRUE;
}

WndItems::WndItems(QSettings * pSettings, QObject * pParent) :
		QObject(pParent),
		m_pSettings(pSettings)
{

}

void WndItems::update(const DWORD dwStyles)
{
	m_map.clear();
	m_dwStyleFilter = dwStyles;

	QTime time;
	time.start();
	::EnumWindows(EnumWindowsProc, (LPARAM) this);
	qDebug() << time.elapsed();
}

void WndItems::populateMenu(QMenu & menu, QAction * before)
{
	WndItemsMap tmpMap = m_map;

	QList<QAction*> oldActions = menu.actions();

	// clear actionions for windows which are not used
	foreach (QAction* pOldAction, oldActions)
	{
		if (!pOldAction->data().toUInt())
			continue;

		const HWND hWnd = (HWND) pOldAction->data().toUInt();

		if (tmpMap.contains(hWnd))// if the action's window is not in the list
		{
			// update the shortcut key
			pOldAction->setShortcut(tmpMap[hWnd]->hotKey());
			tmpMap.remove(hWnd);
		}
		else // else remove it from the list
		{
			menu.removeAction(pOldAction);
			delete pOldAction;
		}
	}

	// now create actions list with the remaining items
	QList<QAction*> newActions;

	foreach (SPWndItem itm, tmpMap)
	{
		QWndAction * newAction =
				new QWndAction(itm->title(), &menu);

		newAction->setHwnd(itm->hwnd());

		newAction->setCheckable(true);
		newAction->setChecked(::IsWindowVisible(itm->hwnd()));

		connect(newAction, SIGNAL(toggled(bool)),
				newAction, SLOT(setWndVisible(bool)));

		newAction->setShortcut(itm->hotKey());

		newActions.push_back(newAction);
	}

	menu.insertActions(before, newActions);
}

void WndItems::populateListWidget(QListWidget & list)
{
	WndItemsMap tmpMap = m_map;

	const int nListItems = list.count();

	for (int i = nListItems - 1; i >= 0; i--)
	{
		QListWidgetItem * pItem = list.item(i);

		HWND hWnd = (HWND) pItem->data(Qt::UserRole).toUInt();
		if (tmpMap.contains(hWnd))// if the action's window is not in the list
		{
			// update the shortcut key
			pItem->setText(tmpMap[hWnd]->title() + "\t" + tmpMap[hWnd]->hotKey());
			tmpMap.remove(hWnd);
		}
		else // else remove it from the list
		{
			list.removeItemWidget(pItem);
		}
	}

	// now create actions list with the remaining items
	foreach (SPWndItem itm, tmpMap)
	{
		const QString sText = itm->title() + "\t" + itm->hotKey();
		QListWidgetItem * newItem =
				new QListWidgetItem(sText);

		newItem->setData(Qt::UserRole, QVariant((uint)itm->hwnd()));

		list.addItem(newItem);
	}
}

////////////////////////////////////////////////////////////////////////////

WndItem::WndItem(const HWND hWnd, const QString &sTitle, const QString &sWndClassName):
		m_hWnd(hWnd),
		m_sWndTitle(sTitle),
		m_sClassName(sWndClassName)
{

}

void WndItem::loadHotKey(QSettings & settings)
{
	m_hotKey.dwHotKey = settings.value(QString("wndItems/%1").arg(m_sClassName), QVariant(0)).toUInt();
}

void WndItem::saveHotKey(QSettings & settings)
{
	settings.setValue(QString("wndItems/%1").arg(m_sClassName), QVariant((uint) m_hotKey.dwHotKey));
}

QString WndItem::hotKey() const
{
	QString sKey;
	if (m_hotKey.W.wModifier & MOD_CONTROL)
		sKey += tr("Ctrl");

	if (m_hotKey.W.wModifier & MOD_ALT)
	{
		if (!sKey.isEmpty())
			sKey += "+";
		sKey += "Alt";
	}

	if (m_hotKey.W.wModifier & MOD_SHIFT)
	{
		if (!sKey.isEmpty())
			sKey += "+";
		sKey += "Shift";
	}

	if (m_hotKey.W.wKey)
	{
		if (!sKey.isEmpty())
			sKey += "+";
		sKey += m_hotKey.W.wKey;
	}
	return sKey;
}

void WndItem::setHotKey(const QString & sHotKey)
{
	m_hotKey.W.wModifier = 0;
	if (sHotKey.contains("Ctrl", Qt::CaseInsensitive))
		m_hotKey.W.wModifier |= MOD_CONTROL;

	if (sHotKey.contains("Alt", Qt::CaseInsensitive))
		m_hotKey.W.wModifier |= MOD_ALT;

	if (sHotKey.contains("Shift", Qt::CaseInsensitive))
		m_hotKey.W.wModifier |= MOD_SHIFT;

	m_hotKey.W.wKey = (WORD) sHotKey.toAscii().right(1).at(0);
}

void WndItem::showWindow(bool bShow)
{
	if (::IsWindow(m_hWnd))
		::ShowWindow(m_hWnd, bShow ? SW_SHOW : SW_HIDE);
}
